package com.cynteka.cyfoman.core.collection;

import com.cynteka.cyfoman.core.ComplexPropertyResolver;
import com.cynteka.cyfoman.core.IPropertyResolver;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

/**
 * User: Sergey
 * Date: 05.08.11
 * Time: 11:45
 */
public class GeneralLinkAppender implements IRegistryAppender {
    private String linkId = "generalLink";
    private String collectionSourceId;
    private String collectionDestinationId;
    private String sourceReferenceFieldName;
    private String destinationParamName;
    private LinkType linkType = LinkType.ONE_TO_MANY;
    private IPropertyResolver propertyResolver = new ComplexPropertyResolver();

    public IPropertyResolver getPropertyResolver() {
        return propertyResolver;
    }

    public void setPropertyResolver(IPropertyResolver propertyResolver) {
        this.propertyResolver = propertyResolver;
    }

    public LinkType getLinkType() {
        return linkType;
    }

    public void setLinkType(LinkType linkType) {
        this.linkType = linkType;
    }

    public String getLinkId() {
        return linkId;
    }

    public void setLinkId(String linkId) {
        this.linkId = linkId;
    }

    public String getCollectionSourceId() {
        return collectionSourceId;
    }

    public void setCollectionSourceId(String collectionSourceId) {
        this.collectionSourceId = collectionSourceId;
    }

    public String getCollectionDestinationId() {
        return collectionDestinationId;
    }

    public void setCollectionDestinationId(String collectionDestinationId) {
        this.collectionDestinationId = collectionDestinationId;
    }

    public String getSourceReferenceFieldName() {
        return sourceReferenceFieldName;
    }

    public void setSourceReferenceFieldName(String sourceReferenceFieldName) {
        this.sourceReferenceFieldName = sourceReferenceFieldName;
    }

    public String getDestinationParamName() {
        return destinationParamName;
    }

    public void setDestinationParamName(String destinationParamName) {
        this.destinationParamName = destinationParamName;
    }

    @Override
    public ICollection[] getCollections() {
        return new ICollection[0];
    }

    @Override
    public ILink[] getLinks() {
        checkNull();
        return new ILink[]{new Link()};
    }

    protected void checkNull() {
        if(propertyResolver == null)
            throw new NullPointerException("propertyResolver can not be null");
        if(collectionSourceId == null)
            throw new NullPointerException("collectionSourceId can not be null");
        if(collectionDestinationId == null)
            throw new NullPointerException("collectionDestinationId can not be null");
        if(linkType == null)
            throw new NullPointerException("linkType can not be null");
        if(sourceReferenceFieldName == null)
            throw new NullPointerException("sourceReferenceFieldName can not be null");
        if(destinationParamName == null)
            throw new NullPointerException("destinationParamName can not be null");
    }

    private class Link extends BaseLink {

        public Link() {
            super(linkId, collectionSourceId, collectionDestinationId, linkType);
        }

        @Override
        public Collection getDestinationItems(Object o) {
            Object refValue = propertyResolver.getProperty(o, sourceReferenceFieldName);
            Map params = new HashMap();
            params.put(destinationParamName, refValue);
            ICollection destCollection = getOwner().getCollection(collectionDestinationId);
            Collection res = destCollection.getItems(params);
            return res;
        }

        @Override
        public Collection getSourceItems(Object o) {
            throw new IllegalStateException("Link does not support this operation");
        }
    }
}
